package com.ziven.common.widget.app;

import android.app.Application;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.ziven.easygo.EasyGos;
import com.ziven.easygo.design.mvp.AbstractOneData;
import com.ziven.easygo.overall.IDispatch;
import com.ziven.easygo.overall.IOverall;
import com.ziven.easygo.overall.OverallModel;
import com.ziven.easygo.simply.EasyGoReceiver;
import com.ziven.easygo.ui.AbstractBaseActivity;
import com.ziven.easygo.ui.AbstractEasyAdapter;
import com.ziven.easygo.ui.AbstractEasyViewHolder;
import com.ziven.easygo.ui.AbstractOneDataActivity;
import com.ziven.easygo.ui.AbstractOneDataFragment;
import com.ziven.easygo.ui.AbstractTypeAdapter;
import com.ziven.easygo.ui.AbstractTypeData;
import com.ziven.easygo.ui.EmptyOneDataFragment;
import com.ziven.easygo.ui.IEasyView;
import com.ziven.easygo.ui.OnItemClickListener;
import com.ziven.easygo.util.EasyUtils;
import com.ziven.easygo.util.LogHelper;
import com.ziven.easygo.util.ViewHelper;

/**
 * @author Aiven
 */
public final class EasyApp {

    private static final String TAG = "EasyApp:";

    private EasyApp () {}

    public static abstract class EasyActivity extends AbstractBaseActivity {

        private EasySpate easySpate;

        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(easySpate != null) {
                easySpate.clearFilter(this);
            }
        }

        protected EasySpate easySpate() {
            if(easySpate == null) {
                easySpate = EasySpate.newInstance(this);
            }
            return easySpate;
        }
    }

    public static abstract class EasyModelActivity extends AbstractOneDataActivity {

        private EasySpate easySpate;

        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(easySpate != null) {
                easySpate.clearFilter(this);
            }
        }

        protected EasySpate easySpate() {
            if(easySpate == null) {
                easySpate = EasySpate.newInstance(this);
            }
            return easySpate;
        }
    }

    public static abstract class EasyFragment extends EmptyOneDataFragment {}

    public static abstract class EasyModelFragment extends AbstractOneDataFragment {}

    public static abstract class EasyTypeData extends AbstractTypeData {}

    public static abstract class EasyHolder<D> extends AbstractEasyViewHolder<D> {

        public EasyHolder(@NonNull View itemView) {
            super(itemView);
        }

        public EasyHolder(@NonNull ViewGroup parent, int layoutId) {
            super(parent, layoutId);
        }

        @Override
        public  <T extends View> T getView(int id) {
            return super.getView(id);
        }

        @NonNull
        @Override
        public ViewHelper<View> getViewHelper(int id) {
            return super.getViewHelper(id);
        }
    }

    public static abstract class EasyAdapter<D, H extends EasyHolder<D>> extends AbstractEasyAdapter<D, H> {}

    public static abstract class EasyTypeAdapter<D extends EasyTypeData, H extends EasyHolder<D>> extends AbstractTypeAdapter<D, H> {}

    public interface EasyClick<D> extends OnItemClickListener<D> {}

    public interface EasyView extends IEasyView {}

    public static abstract class RecyclerActivity<D extends EasyTypeData> extends EasyModelActivity {

        public static final int CODE_CLEAR = 100;
        private EasyTypeAdapter<D, EasyHolder<D>> adapter;

        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            initRecyclerView();
        }

        private void initRecyclerView() {
            if(adapter == null) {
                adapter = newEasyTypeAdapter();
                Object view = obtainRecyclerView();
                RecyclerView rv = view instanceof RecyclerView
                        ? (RecyclerView) view
                        : view instanceof Integer
                        ? getView((Integer) view)
                        : null;
                if(rv != null) {
                    rv.setLayoutManager(newLayoutManager());
                    rv.setAdapter(adapter);
                }
            }
        }

        /**
         * Obtain RecyclerView or RecyclerView Id
         * @return RecyclerView or RecyclerView Id
         */
        @NonNull
        protected abstract Object obtainRecyclerView();

        @NonNull
        protected RecyclerView.LayoutManager newLayoutManager() {
            return new LinearLayoutManager(this);
        }

        @NonNull
        protected EasyTypeAdapter<D, EasyHolder<D>> newEasyTypeAdapter() {
            return new EasyTypeAdapter<D, EasyHolder<D>>() {
                @NonNull
                @Override
                public EasyHolder<D> onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                    Object item = obtainItemView();
                    return item instanceof View
                            ? newEasyHolder((View) item)
                            : item instanceof Integer
                            ? newEasyHolder(parent, (int) item)
                            : newViewHolder(parent, viewType);
                }
            };
        }

        /**
         * Obtain ItemView
         * @return
         * View : itemView,
         * int: itemView layoutId
         * other: do nothing
         */
        protected abstract Object obtainItemView();

        protected EasyHolder<D> newViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new EasyHolder<D>(new View(parent.getContext())) {
                @Override
                protected void bindLayout(D data, int position) {}
            };
        }

        private EasyHolder<D> newEasyHolder(@NonNull View view) {
            return new EasyHolder<D>(view) {

                @Override
                protected void bindLayout(D data, int position) {
                    bindViewData(this, data, position);
                }
            };
        }

        private EasyHolder<D> newEasyHolder(@NonNull ViewGroup parent, int itemViewId) {
            return new EasyHolder<D>(parent, itemViewId) {

                @Override
                protected void bindLayout(D data, int position) {
                    bindViewData(this, data, position);
                }
            };
        }

        /**
         * Bind data to view
         * @param holder EasyHolder
         * @param data EasyTypeData
         * @param position Position
         */
        protected abstract void bindViewData(@NonNull EasyHolder<D> holder, D data, int position);

        @Override
        public void layoutOneData(@NonNull AbstractOneData data) {
            LogHelper.log(TAG + data);
            initRecyclerView();
            if(CODE_CLEAR == data.getOneCode()) {
                adapter.getDataProvider().clear();
            }
            adapter.getDataProvider().addList(data.getOneData());
            EasyUtils.notifyDataSetChanged(adapter);
        }
    }

    public static abstract class EasyApplication extends Application
            implements EasyGoReceiver.IAction, IOverall<IDispatch>, IDispatch {

        @Override
        public void onCreate() {
            super.onCreate();
            EasyGos.init(this, isLog());
            created();
        }

        @Override
        public String[] actions() {
            return new String[0];
        }

        @Override
        public IDispatch getDispatch() {
            return this;
        }

        @NonNull
        @Override
        public OverallModel newModel() {
            return OverallModel.EMPTY;
        }

        /**
         * After onCreate()
         */
        public abstract void created();

        /**
         * Is print log
         * @return true : print, false : not print
         */
        public abstract boolean isLog();
    }
}
